package com.flyme.module.auth.provider.controller;

import com.alibaba.fastjson.JSONObject;
import com.flyme.common.core.configuration.GatewayProperties;
import com.flyme.common.core.http.OpenRestTemplate;
import com.flyme.common.core.model.ResultBody;
import com.flyme.module.auth.client.constants.AuthConstants;
import com.flyme.module.auth.provider.service.feign.SystemAccountClient;
import com.flyme.module.auth.provider.service.impl.QQAuthServiceImpl;
import com.flyme.module.auth.provider.service.impl.WechatAuthServiceImpl;
import com.flyme.module.auth.provider.service.impl.WeiBoAuthServiceImpl;
import com.flyme.module.base.client.entity.SystemAccount;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author: liuyadu
 * @date: 2018/10/29 15:59
 * @description:
 */
@Controller
public class IndexController {
    @Autowired
    private JdbcClientDetailsService clientDetailsService;
    @Autowired
    private QQAuthServiceImpl qqAuthService;

    @Autowired
    private OpenRestTemplate openRestTemplate;
    @Autowired
    private GatewayProperties gatewayProperties;
    @Autowired
    private SystemAccountClient systemAccountClient;
    @Autowired
    private WechatAuthServiceImpl wechatAuthService;

    @Autowired
    private WeiBoAuthServiceImpl weiBoAuthService;

    /**
     * 欢迎页
     *
     * @return
     */
    @GetMapping("/")
    public String welcome() {
        return "welcome";
    }

    /**
     * 登录页
     *
     * @return
     */
    @GetMapping("/login")
    public String login() {
        return "login";
    }


    @RequestMapping("/confirm_access")
    public String confirm_access(HttpServletRequest request, HttpSession session, Map model) {
        Map<String, String> scopes = (Map<String, String>) (model.containsKey("scopes") ? model.get("scopes") : request.getAttribute("scopes"));
        List<String> scopeList = new ArrayList<String>();
        for (String scope : scopes.keySet()) {
            scopeList.add(scope);
        }
        model.put("scopeList", scopeList);
        Object auth = session.getAttribute("authorizationRequest");
        if (auth != null) {
            try {
                AuthorizationRequest authorizationRequest = (AuthorizationRequest) auth;
                ClientDetails clientDetails = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId());
                model.put("app", clientDetails.getAdditionalInformation());
            } catch (Exception e) {

            }
        }
        return "confirm_access";
    }

    /**
     * QQ第三方登录回调
     *
     * @param code code
     * @return
     */
    @GetMapping("/oauth/qq/callback")
    public String oauthByQQ(@RequestParam(value = "code") String code, @RequestHeader HttpHeaders headers) {
        System.out.println("QQ登录回调code##################" + code);
        Map<String, String> map = qqAuthService.getAccessToken(code);
        String accessToken = map.get("access_token");
        System.out.println("QQ登录回调accessToken##################" + accessToken);
        String token = "";
        if (accessToken != null) {
            String openId = qqAuthService.getOpenId(token);
            if (openId != null) {
                systemAccountClient.registerThirdPartyAccount(openId, openId,null, AuthConstants.LOGIN_QQ);
                token = getToken(openId, openId, AuthConstants.LOGIN_QQ, headers);
            }
        }
        System.out.print("redirect:" + qqAuthService.getLoginSuccessUrl() + "?token=" + token);
        return "redirect:" + qqAuthService.getLoginSuccessUrl() + "?token=" + token;
    }

    /**
     * 第三方登录获取token
     *
     * @param userName
     * @param password
     * @param type
     * @param headers
     * @return
     */
    private String getToken(String userName, String password, String type, HttpHeaders headers) {
        // 使用oauth2密码模式登录.
        MultiValueMap<String, Object> postParameters = new LinkedMultiValueMap<>();
        postParameters.add("username", userName);
        postParameters.add("password", password);
        postParameters.add("client_id", gatewayProperties.getClientId());
        postParameters.add("client_secret", gatewayProperties.getClientSecret());
        postParameters.add("grant_type", "password");
        // 添加请求头区分,第三方登录
        headers.add(AuthConstants.HEADER_X_THIRDPARTY_LOGIN, type);
        // 使用客户端的请求头,发起请求
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        // 强制移除 原来的请求头,防止token失效
        headers.remove(HttpHeaders.AUTHORIZATION);
        HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity(postParameters, headers);
        JSONObject result = openRestTemplate.postForObject(gatewayProperties.getAccessTokenUri(), request, JSONObject.class);
        if (result.containsKey("access_token")) {
            return result.getString("access_token");
        }
        return null;
    }


    /**
     * 微信第三方登录回调
     *
     * @param code
     * @return
     */
    @GetMapping("/oauth/wechat/callback")
    public String oauthByWechat(@RequestParam(value = "code") String code, @RequestHeader HttpHeaders headers) {
        Map<String, String> map = wechatAuthService.getAccessToken(code);
        String accessToken = map.get("access_token");
        String url = "";
        SystemAccount account;
        if (accessToken != null) {
            String openId = map.get("openid");
            String unionid = map.get("unionid");
            if (openId != null) {
                JSONObject object = wechatAuthService.getUserInfo(accessToken, openId);
                System.out.println("用户信息:" + object.toJSONString());
                String userhead = object.getString("headimgurl");
                String nickname = object.getString("nickname");
                try {
                    nickname = new String(Base64.decodeBase64(Base64.encodeBase64String(nickname.getBytes("UTF-8"))), "UTF-8");
                } catch (Exception e) {
                }
                ResultBody<SystemAccount> resultBody = systemAccountClient.registerThirdPartyAccount(unionid, userhead,nickname,AuthConstants.LOGIN_WECHAT);
                //token = getToken(openId, openId, AuthConstants.LOGIN_WECHAT, headers);
                account = resultBody.getData();
                if (account.getUserId() == null) {
                    url = wechatAuthService.getLoginSuccessUrl() + "?accountId=" + account.getId() + "&username=" + account.getAccount() + "&type=b";  //未绑定手机号
                } else {
                    url = wechatAuthService.getLoginSuccessUrl() + "?accountId=" + account.getId() + "&username=" + account.getAccount() + "&type=n";   //已绑定手机号
                }
            }
        }
        return "redirect:" + url;
    }

    /**
     * 微博第三方登录回调
     *
     * @param code
     * @return
     */
    @GetMapping("/oauth/weibo/callback")
    public String oauthByWeiBo(@RequestParam(value = "code") String code, @RequestHeader HttpHeaders headers) {
        Map<String, String> map = weiBoAuthService.getAccessToken(code);
        String accessToken = map.get("access_token");
        String url = "";
        SystemAccount account;
        if (accessToken != null) {
            String uid = map.get("uid");
            if (uid != null) {
                JSONObject object = weiBoAuthService.getUserInfo(accessToken, uid);
                System.out.println("用户信息:" + object.toJSONString());
                String name=object.getString("name");
                String profile_image_url=object.getString("profile_image_url");
                System.out.println("uid#######" + uid);
                ResultBody<SystemAccount> resultBody = systemAccountClient.registerThirdPartyAccount(uid, profile_image_url,name, AuthConstants.LOGIN_WEIBO);
                //token = getToken(openId, openId, AuthConstants.LOGIN_WECHAT, headers);
                account = resultBody.getData();
                if (account.getUserId() == null) {
                    url = weiBoAuthService.getLoginSuccessUrl() + "?accountId=" + account.getId() + "&username=" + account.getAccount() + "&type=b";  //未绑定手机号
                } else {
                    url = weiBoAuthService.getLoginSuccessUrl() + "?accountId=" + account.getId() + "&username=" + account.getAccount() + "&type=n";   //已绑定手机号
                }
            }
        }
        return "redirect:" + url;
    }
}
